#pragma once
#include <SDL\SDL.h>
#include <SDL\SDL_image.h>
#include <SDL\SDL_mixer.h>
#include <SDL\SDL_ttf.h>
#include <string>
#include "Board.h"
#include "GlobalStructs.h"
#include "GameStates.h"
#include <utility>
#include <list>
#include "Tile.h" /*-- Added to create tile object --*/
#include "TileParser.h"
using namespace std;

typedef std::list< std::pair<arrowDirection,GameTile> > DirGameTileList;

class GameData {
private:
	/*--- Non-Class Variables ---*/
	SDL_Rect m_handTileOffset;
	SDL_Surface * m_buffer;		// this is the screen we draw to.
	SDL_Surface * m_startMenuBG;
	SDL_Surface * m_tileBGs;
	SDL_Surface * m_tileIcons;		// this is the file that holds the tile icons, arrows, and players
	SDL_Surface * m_boardBG;
	SDL_Surface * m_chooseAction;
	SDL_Surface * m_endGameBG;
	SDL_Surface * m_confirmationBox;
	SDL_Surface * m_choosePlayerPic;
	SDL_Surface * X_Pic;
	SDL_Surface * m_arrowsPic;
	Board * m_gameBoard;		// this is the gameboard for the game.
	Board * m_oldGameBoard;
	bool m_validPlacement[BOARD_ARRAY_SIZE][BOARD_ARRAY_SIZE];
	Position m_mPos;			// mouse position
								//Temp, will be defined in globalDefinitions.h
	GameState m_prevGameState;	// GameStates from GameStates.h enum 
	GameState m_currentGameState;
	GameState m_nextGameState;		// needed for CONFIRM_ACTION state
	int m_activePlayer;			// current player's turn
	char * m_readFile;
	
	Uint32 m_gameTimeStart;		// time game was started (since constructed
	Uint32 m_gameTimeEnd;		// time game was started (since constructed

	Uint32 m_roundStart;
	Uint32 m_roundEnd;
	list<Uint32> m_timeTakenEachRoundList;

	int m_totalPlayers; //number of [players in current game;
	int * m_totalGold; // total gold of a player

	/* Mouse events */
	SDL_MouseButtonEvent m_prevMouse;
	SDL_MouseButtonEvent m_currMouse;

	/* UI elements */
	SDL_Surface * m_btmUI;
	SDL_Surface * m_topUI;
	SDL_Surface * m_scrollUI;
	SDL_Surface * m_barUI; // whats this for
	SDL_Surface * m_messageUI;
	SDL_Surface * m_focusOnActivePlayer;
	SDL_Surface * m_endOfTurn;
	SDL_Surface * m_cancelAction;
	SDL_Surface * m_quitButton;
	TTF_Font * m_font;
	TTF_Font * m_font2;
	TTF_Font * m_font2small;
	TTF_Font * m_font3;
	
	/*--- Member Variables ---*/
	bool m_running;
	bool m_isPressed;
	bool m_isReleased;
	bool m_isGrabbed;
	Tile m_tiles;
	int m_alpha; 
	int m_moveCounter;
	bool m_playerStartedStrongWind;
	// for player move manipulations
	int m_chosenPlayer;
	int m_lastActingPlayer; // for mind control
	bool m_playerIsChosen;
	bool m_playerIsChosenAgain;
	int m_roundsCompleted;
	int m_drakonSummoner; // player id for who summoned drakon (for stats)
	
	// Grabbed Tile variables
	Tile m_grabbedTile;
	Position m_grabbedTilePos;

	// UI Rects
	SDL_Rect m_gridUiRect;
	SDL_Rect m_topUiRect;
	SDL_Rect m_bottomUiRect;
	SDL_Rect m_menuScreenStartButton;
	SDL_Rect m_menuScreenExitButton;
	SDL_Rect m_changeTurnScreen;
	SDL_Rect m_chooseActionRect;
	SDL_Rect m_confirmationRect;
	SDL_Rect m_gameStatePos;
	SDL_Rect m_choosePlayerRect;
	SDL_Rect m_arrowsRect;
	SDL_Rect m_focusOnActivePlayerRect;
	SDL_Rect m_endOfTurnRect;
	SDL_Rect m_cancelActionRect;
	SDL_Rect m_quitButtonRect;
    /*--- music ---*/
	Mix_Music * m_gameMusic;
	Mix_Music * m_titleMusic;
	Mix_Music * m_endGameMusic1;
	Mix_Music * m_endGameMusic2;
	Mix_Chunk * m_click;
	Mix_Chunk * m_drakon;
	Mix_Chunk * m_drakonStart;
	Mix_Chunk * m_destroy;
	Mix_Chunk * m_gainCoin;
	Mix_Chunk * m_loseCoin;
	Mix_Chunk * m_harp;
	Mix_Chunk * m_playerMove;
	Mix_Chunk * m_magicalShiftWav;
	Mix_Chunk * m_placeTileSound;
	Mix_Chunk * m_endTurnWav;
	Mix_Chunk * m_teleport;
	Mix_Chunk * m_mindControl;
	Mix_Chunk * m_rotateStartWav;
	Mix_Chunk * m_rotateUpWav;
	Mix_Chunk * m_rotateDownWav;
	Mix_Chunk * m_masterKey;
	Mix_Chunk * m_wind;
	Mix_Chunk * m_movePlayer;
	Mix_Chunk * m_dropTileInvalidAreaWav;
	int m_currentEndGameMusic;
	bool m_moveSoundPlayed;

	/*--- Window ---*/
	bool m_windowed;
public:
	/*--- Constructors ---*/
	/*
	IN: a_screen - sends the created screen in main to this class that does all the drawing.
	by default m_running is true, thus is unnecessary in the initializer list.
	*/
	GameData(SDL_Surface * a_screen);
	~GameData();
	/*--- Game Functions ---*/
	/*
	this does game logic, physics, framerate, and calculations.  This is also the name that
	is universally recognized. Player and ai states are also updated here.
	*/
	void initializePlayers(void);
	void initializeRects(void);
	void update();
	void checkValidPlacement(Tile a_tile);
	// for rotate tile on board
	void checkValidPlacement2(Tile a_tile);
	void checkValidPlacement3(Tile a_tile);
	/*
	Does not need anything passed into it.  As m_buffer contains the screen.
	*/
	void drawDimBoard(void);
	void draw();
	void gameLoop();
	void handleInput(); // handles any and all events that occur
	void changeTurn();
	void release();
	/*--- Accessors ---*/
	bool isRunning() { return m_running; }
	// Converts screen coords (XY) to board coords (row & column)
	Position convertScreenCoordsToGridPos(Position pos);
	Position convertScreenCoordsToGridPos(int mouseX, int mouseY);
	int getHandlistTileIndex(int mouseX, int mouseY);
	bool canMoveTwice(Position posOnBoard);
	bool canMoveOnce(Position posOnBoard);
	bool canPlace(Tile thisTile, Position columnRow);
	//list<GameTile> getNeighbors(Position columnRow);  
	DirGameTileList getNeighbors(Position columnRow);

	list<GameTile> getPossiblePlayerMovements(Position posOnBoard);
	GameTile getNeighbor(Position pos, arrowDirection dir);
	list<Tile> checkValidRotationOnPosCW(Position pos);
	list<Tile> checkValidRotationOnPosCCW(Position pos);
private:
	/*--- Game Sub-Functions ---*/
	void handleMouseDown(SDL_Event a_event); // handles the mouse functions
	void handleMouseUp(SDL_Event a_event);
	void handleKey(SDL_Event a_event);   // handles keyboard input
	
	/* Window */
	void toggleFullscreen();

	/* Board Interface */
	void drawMiniMap(void);
	void drawGrabbedTile();
	void drawOverlay();
	void drawTopUI();    // draws the ui on the screen top
	void drawBottomUI(); // draws the ui on the screen bottom
	void drawCurrentState(void);
	void drawTurnChangeScreen(void);
	void drawChoosePlayer(void);
	void drawAlphaRect(int xPos,int yPos,int width,int height,Uint32 col,int alpha);
	void drawScrollArrows(void);
	void displayWindowCaption(void);
	void drawEndGameStatistics(void);
	void showImage(int a_x, int a_y, SDL_Surface * a_source, SDL_Surface * a_destination);
	void blit(SDL_Surface* a_source,SDL_Surface* a_destination,int a_x,int a_y);
	void blitImg(SDL_Surface* a_source,SDL_Surface* a_dest,int a_x,int a_y);
	
	arrowDirection checkIfHarpIsNear(Position tileCoord, Tile tileToCheck);
	void resetValidPlacementArray();
	void updateDrakonTerror();
	void stealPlayerRandomTile(int stealer,int stealee);

	// Functions used in void checkValidPlacement(Tile) function
	bool isExitClear(int,int,arrowDirection,int,int,arrowDirection);
	bool hasNeighbor(int row,int column);
	bool hasNeighbor(Position columnRow, arrowDirection direction);
	
	void getNeighbors(bool*,int,int);
	bool canMove(arrowDirection direction, Position columnRow);
	bool isNeighborUP(int,int);
	bool isNeighborRIGHT(int,int);
	bool isNeighborDOWN(int,int);
	bool isNeighborLEFT(int,int);
	bool isMiddle(int,int);
	bool isTopLeft(int,int);
	bool isTopRight(int,int);
	bool isBottomLeft(int,int);
	bool isBottomRight(int,int);
	bool isTopEdge(int,int);
	bool isRightEdge(int,int);
	bool isBottomEdge(int,int);
	bool isLeftEdge(int,int);

	/* Player Actions */
	bool movePlayerUP(int a_activePlayer);
	bool movePlayerRIGHT(int a_activePlayer);
	bool movePlayerDOWN(int a_activePlayer);
	bool movePlayerLEFT(int a_activePlayer);

	void moveCamUP(void);
	void moveCamRIGHT(void);
	void moveCamDOWN(void);
	void moveCamLEFT(void);
	void centerCamOnPlayer(Player a_activePlayer);

	// Useful for state action-validity checking
	bool isAnyState(GameState state_1);
	bool isAnyState(GameState state_1,GameState state_2);
	bool isAnyState(GameState state_1,GameState state_2,GameState state_3);
	bool isAnyState(GameState state_1,GameState state_2,GameState state_3,GameState state_4);
	bool isAnyState(GameState state_1,GameState state_2,GameState state_3,GameState state_4,GameState state_5);
	bool isAnyState(GameState state_1,GameState state_2,GameState state_3,GameState state_4,GameState state_5,GameState state_6);

	bool isAllState(GameState state_1);
	bool isAllState(GameState state_1,GameState state_2);
	bool isAllState(GameState state_1,GameState state_2,GameState state_3);
	bool isAllState(GameState state_1,GameState state_2,GameState state_3,GameState state_4);
	bool isAllState(GameState state_1,GameState state_2,GameState state_3,GameState state_4,GameState state_5);
	bool isAllState(GameState state_1,GameState state_2,GameState state_3,GameState state_4,GameState state_5,GameState state_6);

	bool isNoneOfState(GameState state_1);
	bool isNoneOfState(GameState state_1,GameState state_2);
	bool isNoneOfState(GameState state_1,GameState state_2,GameState state_3);
	bool isNoneOfState(GameState state_1,GameState state_2,GameState state_3,GameState state_4);
	bool isNoneOfState(GameState state_1,GameState state_2,GameState state_3,GameState state_4,GameState state_5);
	bool isNoneOfState(GameState state_1,GameState state_2,GameState state_3,GameState state_4,GameState state_5,GameState state_6);
	void undo(void);

	// update helpers
	void updateCamera();
	void updateMovePlayerCleanUp();
	void updateConfirmAction();
	void updateSelectAPlayerWhileChosen();
	void updateMovePlayer();
	void updateMoveOtherPlayer();
	void updatePlaceTileCleanUp();
	void updateMoveOtherPlayerCleanUp();
	void updateEndGame();
	void updateEndGameStatistics();
	// handle input helpers
	void handleMouseUpMovePlayer(SDL_Event a_event);
	void handleMouseUpPlaceTile(SDL_Event a_event);
	void handleMouseUpMagicalShift(SDL_Event a_event);
	void handleMouseUpPlaceFloatingTile(SDL_Event a_event);
	void handleMouseUpSelectGametile(SDL_Event a_event);

	void handleMouseDownTitleMenu(SDL_Event a_event);
	void handleMouseDownPlayerTurnChange(SDL_Event a_event);
	void handleMouseDownChooseAction(SDL_Event a_event);
	void handleMouseDownConfirmAction(SDL_Event a_event);
	void handleMouseDownPlaceTile(SDL_Event a_event);
	void handleMouseDownMagicalShift(SDL_Event a_event);
	void handleMouseDownSelectPlayer(SDL_Event a_event);
	void handleMouseDownHandlistArrows(SDL_Event a_event);
	
};